package com.yys.huarongdao;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;


import com.yys.huarongdao.application.MyApplication;
import com.yys.huarongdao.customView.MyGridView;
import com.yys.huarongdao.dao.MySQLiteOpenHelper;
import com.yys.huarongdao.entity.ArrayIcon;
import com.yys.huarongdao.entity.Icon;

import java.util.ArrayList;
import java.util.LinkedList;

public class GameActivity extends AppCompatActivity implements View.OnClickListener {

    private MySQLiteOpenHelper sqLiteOpenHelper;
    private int rankType;

    private static TextView tv_time_counter;
    private TextView tv_step_counter;
    private ImageButton ibut_tip;
    private ImageButton ibut_goBack;
    private ImageButton ibut_pause;
    private ImageButton ibut_restart;
    private ImageButton ibut_exit;
    private MyGridView grid_photo;
    private RelativeLayout layout_center;

    private AnimationSet mAnimationSet;

    private int step;
    private static volatile int time;
//    private int MAX_TIME=0;
    private MyAsyncTask countdownAsyncTask;

    private ArrayList<Icon> mData;
    private ArrayList<Integer> mNumberArrayList;
    private MyAdapter mAdapter;

    private int gameStatus;
    private final int GAME_STATUS_PAUSE =2;
    private final int GAME_STATUS_END=3;
    private final int GAME_STATUS_PLAYING=4;

    private int gameEndType;
    private final int GAME_VICTORY=0;
    private final int GAME_DEFEAT=1;

    private int rankingNum=-1;

    private AlertDialog alertDialog;

    private Bundle savedInstanceState;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(getSupportActionBar()!=null){
            getSupportActionBar().hide();
        }
        //设置全屏
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_game);
        initDate(savedInstanceState);
        bindViews();
        initGameView();
        if(gameStatus==GAME_STATUS_PLAYING)
            countdown();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //销毁监听提示的线程
        grid_photo.destroyIsTipThread();
        time=0;
        step=0;
        //停止异步计时任务线程
        stopCountdown();
        if(alertDialog!=null){
            alertDialog.dismiss();
        }
    }

    /**
     * Activity销毁前，保存数据
     *
     * @param outState
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putIntegerArrayList("mNumberArrayList",mNumberArrayList);
        outState.putInt("step",step);
        outState.putInt("time",time);
        outState.putIntegerArrayList("blankPositions",new ArrayList<Integer>(mAdapter.getBlankPositions()));
        outState.putInt("gameStatus",gameStatus);
        if(gameStatus==GAME_STATUS_END) {
            outState.putInt("gameEndType", gameEndType);
            //保存本局排名
            outState.putInt("rankingNum",rankingNum);
        }
    }

    /**
     * 初始化数据
     * @param savedInstanceState
     */
    private void initDate(Bundle savedInstanceState){
        this.savedInstanceState=savedInstanceState;
        if(savedInstanceState!=null){
            step=savedInstanceState.getInt("step");
            savedInstanceState.putInt("step",0);

            gameStatus=savedInstanceState.getInt("gameStatus");
            savedInstanceState.putInt("gameStatus",0);

            if(gameStatus==GAME_STATUS_END){
                gameEndType=savedInstanceState.getInt("gameEndType");
                savedInstanceState.putInt("gameEndType",-1);

                rankingNum=savedInstanceState.getInt("rankingNum");
                savedInstanceState.putInt("rankingNum",-1);
            }

            time=savedInstanceState.getInt("time");
            savedInstanceState.putInt("time",0);
        }
        if(gameStatus==0){
            setGameStatus(GAME_STATUS_PLAYING);
        }

        rankType = MyApplication.getApplication().getRankType(this);
        //如果application销毁掉，就从文件中拿rankType
        if(rankType==0){
            SharedPreferences sharedPreferences=getSharedPreferences("rankType",MODE_PRIVATE);
            sharedPreferences.getInt("rankType",3);
        }
//        MAX_TIME=rankType*rankType*10;
        if(gameStatus==GAME_STATUS_PAUSE) {
            gameDialog(GAME_STATUS_PAUSE);
        }else if(gameStatus==GAME_STATUS_END){
            gameDialog(gameEndType);
        }
        sqLiteOpenHelper = new MySQLiteOpenHelper(this,"huarongdao.db",null,1);
    }

    @SuppressLint("WrongViewCast")
    private void bindViews(){
        tv_step_counter = findViewById(R.id.tv_step_counter);
        tv_time_counter = findViewById(R.id.tv_time_counter);
        ibut_tip = findViewById(R.id.ibut_tip);
        ibut_goBack = findViewById(R.id.ibut_goBack);
        ibut_pause = findViewById(R.id.ibut_pause);
        ibut_restart = findViewById(R.id.ibut_restart);
        ibut_exit = findViewById(R.id.ibut_exit);
        grid_photo =findViewById(R.id.grid_photo);
        layout_center = findViewById(R.id.layout_center);

        ibut_exit.setOnClickListener(this);
        ibut_goBack.setOnClickListener(this);
        ibut_restart.setOnClickListener(this);
        ibut_pause.setOnClickListener(this);
        ibut_tip.setOnClickListener(this);
        tv_step_counter.setText("步数："+ step);
        tv_time_counter.setText("时间："+time+"秒");
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.ibut_tip:
                tip();
                break;
            case R.id.ibut_goBack:
                goBack();
                break;
            case R.id.ibut_pause:
                gamePause();
                break;
            case R.id.ibut_restart:
                restart();
                break;
            case R.id.ibut_exit:
                stopCountdown();
                finish();
                break;
        }
    }

    /**
     * 提示下一步
     * 1、提示方向
     * 2、选中提示要交换的Item
     * 3、设置item选中后的变化
     */
    private void tip() {
        if(gameStatus!=GAME_STATUS_PLAYING){
            return;
        }
        int colCount=rankType;
        int blankPosition=mAdapter.getCurrentBlankPosition();
        boolean isLeft=blankPosition%colCount!=0;
        boolean isRight=(blankPosition+1)%colCount!=0;
        boolean isUp=blankPosition-colCount>=0;
        boolean isDown=blankPosition+colCount<=colCount*colCount-1;

        int lastBlankPosition;
        if((lastBlankPosition=mAdapter.getLastBlankPosition())!=-1){
            isLeft=isLeft&&lastBlankPosition!=blankPosition-1;
            isRight=isRight&&lastBlankPosition!=blankPosition+1;
            isUp=isUp&&lastBlankPosition!=blankPosition-colCount;
            isDown=isDown&&lastBlankPosition!=blankPosition+colCount;
        }
        int nextBlankPosition=-1;
        if(isLeft){
            nextBlankPosition=blankPosition-1;
        } else if (isUp){
            nextBlankPosition=blankPosition-colCount;
        }else if(isRight){
            nextBlankPosition=blankPosition+1;
        }else if(isDown){
            nextBlankPosition=blankPosition+colCount;
        }
        grid_photo.setTipPosition(nextBlankPosition);

    }

    /**
     * 游戏暂停
     */
    private void gamePause() {
        if(gameStatus!=GAME_STATUS_PLAYING){
            return;
        }
        setGameStatus(GAME_STATUS_PAUSE);
        //停止倒计时
        stopCountdown();
        //暂停弹窗
        gameDialog(GAME_STATUS_PAUSE);
    }

    /**
     * 返回上一步
     */
    private void goBack() {
        if(gameStatus!=GAME_STATUS_PLAYING){
            return;
        }
        if(mAdapter.blankPositions.size()<2)
            return;
        ArrayIcon.goBack(mNumberArrayList,mData,mAdapter.getCurrentBlankPosition(),mAdapter.getLastBlankPosition());
        //栈顶出栈
        mAdapter.removeBlankPosition();
        mAdapter.notifyDataSetChanged();
        tv_step_counter.setText("步数："+ (--step));
    }

    /**
     * 开始计时
     */
    private void countdown(){
//        if(time==0){
//            time=MAX_TIME;
//        }
        countdownAsyncTask=new MyAsyncTask();
        countdownAsyncTask.execute();
    }

    private void reCountdown(){
        time=0;
        countdown();
    }

    private void resumeCountdown(){
        countdownAsyncTask=new MyAsyncTask();
        countdownAsyncTask.execute();
    }

    private void stopCountdown(){
        if(countdownAsyncTask==null)
            return;
        if(!countdownAsyncTask.isCancelled())
            countdownAsyncTask.cancel(true);
    }

    private boolean isStopCountdown(){
        return countdownAsyncTask.isCancelled();
    }

    /**
     * 统计步数
     */
    private void countStep(){
        tv_step_counter.setText("步数："+ (++step));
    }

    private void recountStep(){
        step=0;
        tv_step_counter.setText("步数："+ step);
    }

    /**
     * 初始化游戏界面
     */
    private void initGameView(){
        final int rowCount=rankType;
        final int colCount=rankType;
        grid_photo.setNumColumns(colCount);
        grid_photo.setVerticalSpacing(5);
        grid_photo.setHorizontalSpacing(5);

        //获取grid_photo的宽度。
        int parentWidth=getDisplay().getWidth();
        int parentHeight=getDisplay().getHeight();
        int width=parentWidth>parentHeight?parentHeight:parentWidth;

        RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(width,width);
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        grid_photo.setLayoutParams(params);

        //初始化适配器
        initMAdapter(rowCount,colCount,width);
        //初始化游戏界面
        grid_photo.setAdapter(mAdapter);
        //设置点击监听器
        grid_photo.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if(gameStatus!=GAME_STATUS_PLAYING)
                    return;
                //若是数字是在空格旁边，则交换位置
                if(ArrayIcon.swapItem(mNumberArrayList,mData,position,mAdapter.getCurrentBlankPosition())>-1){
                    mAdapter.addBlankPosition(position);
                    mAdapter.notifyDataSetChanged();
                    countStep();//统计步数
                    if(ArrayIcon.isSuccess(mNumberArrayList)){
                        //停止计时
                        stopCountdown();
                        //跳出弹窗
                        gameDialog(GAME_VICTORY);
                        setGameStatus(GAME_STATUS_END,GAME_VICTORY);
                    }
                }
            }
        });
        //设置提示监听器
        grid_photo.setOnTipListener(new MyGridView.OnTipListener() {
            @Override
            public void onTip(int tipPosition) {
                setAnimation(grid_photo.getChildAt(tipPosition));
            }
        });
        mAdapter.notifyDataSetChanged();
    }

    /**
     * 初始化适配器
     * 1、获取有解的数字序列
     * 2、初始化mData
     * 3、初始化适配器
     */
    private void initMAdapter(int rowCount, int colCount, int parentWidth){
        LinkedList<Integer> blankPositions=null;

        //获取缓存数据
        if(savedInstanceState!=null){
            //获取有解数列缓存数据
            mNumberArrayList=savedInstanceState.getIntegerArrayList("mNumberArrayList");
            savedInstanceState.putIntegerArrayList("mNumberArrayList",null);

            //获取空白图片轨迹List。缓存数据
            ArrayList<Integer> array_blankPositions=savedInstanceState.getIntegerArrayList("blankPositions");
            savedInstanceState.putIntegerArrayList("blankPositions",null);
            if(array_blankPositions!=null){
                blankPositions=new LinkedList<Integer>(array_blankPositions);
            }
        }
        //获取有解数列
        if(mNumberArrayList==null){
            mNumberArrayList=ArrayIcon.getNumberArrayList(rowCount*colCount);
        }
        //获取有解的图片序列
        mData=ArrayIcon.getIconArrayList(mNumberArrayList);

        //获取空白图片轨迹List
        if(blankPositions!=null){
            mAdapter=new MyAdapter(mData,GameActivity.this,blankPositions,parentWidth);
        }else{
            mAdapter=new MyAdapter(mData,GameActivity.this,parentWidth);
        }


    }

    /**
     * 游戏时的弹窗
     * @param dialogType 游戏胜负结果
     */
    private void gameDialog(final int dialogType){
        AlertDialog.Builder builder=new AlertDialog.Builder(GameActivity.this);
        View view=getLayoutInflater().inflate(R.layout.dialog_game_status,null,false);

        builder.setCancelable(false);
        builder.setView(view);
        alertDialog = builder.create();
        alertDialog.show();

        ImageView dialog_img_title=view.findViewById(R.id.dialog_img_title);
        TextView dialog_tv_time = view.findViewById(R.id.dialog_tv_time);
        TextView dialog_tv_step = view.findViewById(R.id.dialog_tv_step);
        TextView dialog_tv_rankingList=view.findViewById(R.id.dialog_tv_rankingList);
        ImageView dialog_ibut_cancel =view.findViewById(R.id.dialog_ibut_cancel);
        Button dialog_but_startAgain = view.findViewById(R.id.dialog_but_startAgain);

        dialog_tv_time.setText("时间："+time+"秒");
        dialog_tv_step.setText("步数："+step);

        if(dialogType==GAME_VICTORY){
            int rankingNum=getRanking(time,step);
            if(rankingNum!=-1){
                dialog_tv_rankingList.setText("排行榜：第"+rankingNum+"名");
            }
            else{
                dialog_tv_rankingList.setText("排行榜：未上榜");
            }

            dialog_img_title.setImageResource(R.drawable.game_victory);
        }else if(dialogType==GAME_DEFEAT){
            dialog_tv_rankingList.setText("排行榜：未上榜");
            dialog_img_title.setImageResource(R.drawable.game_defeat);
        }else {
            dialog_tv_rankingList.setText("排行榜：未结算");
            dialog_img_title.setImageResource(R.drawable.game_pause);
            dialog_but_startAgain.setText("继续游戏");
        }
        
        dialog_ibut_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(dialogType== GAME_STATUS_PAUSE){
                    resumeCountdown();
                    setGameStatus(GAME_STATUS_PLAYING);
                }

                alertDialog.dismiss();
            }
        });
        dialog_but_startAgain.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(dialogType== GAME_STATUS_PAUSE){
                    setGameStatus(GAME_STATUS_PLAYING);
                    resumeCountdown();
                }
                else
                    restart();
                alertDialog.dismiss();
            }
        });
    }

    /**
     * 获取排名
     * 1、判断是否进入了排行榜
     * 2、替换最后一名
     * 3、排序遍历
     * 4、遍历出刚更改的记录，计算出排名
     */
    private int getRanking(int timeSpent,int stepSpent){
        if(rankingNum!=-1)
            return rankingNum;

        long currentTime=System.currentTimeMillis();

        SQLiteDatabase writeDB=sqLiteOpenHelper.getWritableDatabase();
        Cursor rankingListCursor= writeDB.rawQuery("select time_spent,rank_id from ranking_list where rank_type=? order by time_spent desc,date desc",new String[]{String.valueOf(rankType)});

        boolean isFull= rankingListCursor.getCount()>=10;
        /**
         * 入了排行榜
         * 1、准备数据
         * 2、判断是否满人，替换最后一名记录或添加记录
         * 3、再次排序遍历，计算出排名
         */
        //1、准备数据
        String account=MyApplication.getApplication().getAccount();
        if(account==null)
            return rankingNum=-1;
        Cursor userCursor=writeDB.rawQuery("select userid from user where account=?",new String[]{account});
        if(!userCursor.moveToFirst())
            return rankingNum=-1;
        String userId=userCursor.getString(userCursor.getColumnIndex("userid"));
        String rankId;

        //2.1、排行榜满十人，替换最后一名
        if(isFull){
            //判断是否进入了排行榜
            if(!rankingListCursor.moveToFirst())
                return rankingNum=-1;
            int lastTimeSpent=rankingListCursor.getInt(rankingListCursor.getColumnIndex("time_spent"));
            if(timeSpent>=lastTimeSpent){
                //没进排行榜
                return rankingNum=-1;
            }
            rankId=rankingListCursor.getString(rankingListCursor.getColumnIndex("rank_id"));
            String args[]=new String[]{userId,String.valueOf(timeSpent), String.valueOf(currentTime), String.valueOf(stepSpent),rankId};
            writeDB.execSQL("update ranking_list set userid=?,time_spent=?,date=?,step_spent=? where rank_id=?",args);
        }
        //2.2、排行榜未满十人，添加记录
        else {
            String args[]=new String[]{userId,String.valueOf(timeSpent), String.valueOf(currentTime), String.valueOf(stepSpent), String.valueOf(rankType)};
            writeDB.execSQL("insert into ranking_list(userid,time_spent,date,step_spent,rank_type) values(?,?,?,?,?)",args);
            rankingListCursor=writeDB.rawQuery("select last_insert_rowid() from ranking_list where rank_type=?",new String[]{String.valueOf(rankType)});
            if(!rankingListCursor.moveToFirst())
                return rankingNum=-1;
            rankId=rankingListCursor.getString(0);
        }

        //3、再次排序遍历，计算出排名
        rankingListCursor= writeDB.rawQuery("select * from ranking_list where rank_type=? order by time_spent asc,date asc",new String[]{String.valueOf(rankType)});
        int count=0;
;
        if(rankingListCursor.moveToFirst()){
            do{
                count++;
                if(rankingListCursor.getString(rankingListCursor.getColumnIndex("rank_id")).equals(rankId)){
                    return rankingNum=count;
                }
            }while (rankingListCursor.moveToNext());
        }
        return rankingNum;
    }

    /**
     * 再玩一局
     * 1、初始化变量
     * 2、初始化游戏界面
     * 3、重新统计时间
     */
    private void restart() {
        //初始化变量
        mData=null;
        mAdapter=null;
        mNumberArrayList=null;

        //初始化游戏界面
        initGameView();

        //重置步数
        recountStep();
        //重新统计时间
        if(countdownAsyncTask!=null&&!isStopCountdown())
            stopCountdown();
        reCountdown();
        setGameStatus(GAME_STATUS_PLAYING);
    }

    /**
     * 为view设置动画。在这里主要用作提示下一步
     * @param view
     */
    public void setAnimation(View view) {
        AnimationSet animationSet = new AnimationSet(true);
        if (mAnimationSet != null && mAnimationSet != animationSet) {
            mAnimationSet.setFillAfter(false);
            mAnimationSet.cancel();
        }
         ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.2f, 1.0f,
         1.2f, 1, 0.5f, 1, 0.5f);
        ;
        AlphaAnimation alphaAnimation=new AlphaAnimation(1,0.5f);
        animationSet.addAnimation(alphaAnimation);
        animationSet.addAnimation(scaleAnimation);
        animationSet.setFillAfter(true);
        view.startAnimation(animationSet);
        mAnimationSet = animationSet;
    }

    private void setGameStatus(int ...gameStatusAndEndType){
        this.gameStatus=gameStatusAndEndType[0];
        if(gameStatusAndEndType[0]==GAME_STATUS_END)
            setGameEndType(gameStatusAndEndType[1]);
        else
            setGameEndType(-1);
    }

    private void setGameEndType(int gameEndType){
        this.gameEndType=gameEndType;
    }
    /**
     * 倒计时异步任务
     */
    public class MyAsyncTask extends AsyncTask{

        @Override
        protected Object doInBackground(Object[] objects) {
            while (time>=0){
                if(isCancelled())
                    return null;
                publishProgress();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Object[] values) {
//            if(time>0)
//                tv_time_counter.setText("倒计时："+(--time)+"秒");
//            else  if(time==0){
//                setGameStatus(GAME_STATUS_END,GAME_DEFEAT);
//                GameActivity.this.gameDialog(GAME_DEFEAT);
//            }
            tv_time_counter.setText("时间："+(time++)+"秒");
        }
    }

    /**
     * GridView适配器
     */
    public class MyAdapter extends BaseAdapter{

        private ArrayList<Icon> mData;
        private int colCount;
        private Context mContext;
        private LinkedList<Integer> blankPositions;
        private int parentWidth;

        public MyAdapter(ArrayList<Icon> mData, Context mContext,@Nullable int parentWidth) {
            this.mData = mData;
            this.colCount=(int)Math.sqrt(mData.size());
            this.mContext = mContext;
            initBlankPosition();
            this.parentWidth=parentWidth;

        }

        public MyAdapter(ArrayList<Icon> mData, Context mContext,LinkedList<Integer> blankPositions,@Nullable int parentWidth) {
            this.mData = mData;
            this.colCount=(int)Math.sqrt(mData.size());
            this.mContext = mContext;
            this.blankPositions=blankPositions;
            this.parentWidth=parentWidth;
        }

        public void setBlankPositions(LinkedList<Integer> blankPositions) {
            this.blankPositions = blankPositions;
        }

        private void initBlankPosition(){
            this.blankPositions = new  LinkedList<Integer>();
            for(int i=0;i<this.mData.size();i++){
                if(this.mData.get(i).getiId()==R.drawable.blank){
                    blankPositions.add(i);
                    return;
                }
            }
        }

        public int getCurrentBlankPosition(){
            return this.blankPositions.getLast();
        }

        public int getLastBlankPosition(){
            if(blankPositions.size()>=2)
                return this.blankPositions.get(this.blankPositions.size()-2);
            else
                return -1;
        }

        public void addBlankPosition(int blankPosition){
            this.blankPositions.add(blankPosition);
        }

        public void removeBlankPosition(){
            this.blankPositions.removeLast();
        }

        public LinkedList<Integer> getBlankPositions() {
            return blankPositions;
        }

        @Override
        public int getCount() {
            return mData.size();
        }

        @Override
        public Object getItem(int position) {
            return mData.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_grid_icon,parent,false);
            ImageView img_icon = convertView.findViewById(R.id.img_icon);
            img_icon.setBackgroundResource(mData.get(position).getiId());

            int width=(parentWidth-5*(colCount-1))/colCount;
            ViewGroup.LayoutParams params=new RelativeLayout.LayoutParams(width,width);
            convertView.setLayoutParams(params);
            return convertView;
        }
    }

}
